AWS SDK for Python (Boto)からAmazon Transcribeを使って文字起こししてみた
Amazon の提供する文字起こしサービス Amazon Transcribe を AWS SDK for Python (Boto) から触ってみました。
AWS CLI からの操作は次の記事を参照下さい。
前提
サービス提供リージョン
Amazon Transcribe は 2018/04/05 に一般提供となりました。
ただし、現時点では以下の一部リージョンでのみ利用可能です。
- N. Virginia
- Ohio
- Oregon
- Ireland
東京リージョンでは利用できないため、お気をつけ下さい。
今回は N. Virginia リージョンで検証します。
対応言語
現時点では
- 米語
- スペイン語
にのみ対応しています。
日本語には対応していないため、お気をつけ下さい。
検証環境
- Amazon Linux
- Python 3.6
処理の流れ
Amazon Transcribe の処理の流れを図にまとめます。
ポイントは、インプット(文字起こししたいメディア)とアウトプット(文字起こしテキスト)が異なる AWS アカウントの S3 バケットに保存される点です。
ユーザーの管理する S3 バケットに文字起こししたいメディアをアップロードし、このメディアを Amazon Transcribe が読み取れるように、バケットポリシーを変更します。
文字起こし後のテキストは Amazon Transcribe 管轄の S3 バケットに保存されます。
以下に注意して下さい。
- ユーザーの管理する S3 バケットに対して Amazon Transcribe が書き込めるようなバケットポリシーの設定は不要
- Amazon Transcribe が管理する S3 バケットにある文字起こし後のテキストは presigned URL 経由で取得
作業の流れ
以下の流れで作業します。
- 音源をアップロードする S3 バケットの作成(AWS CLIを利用)
- 音源のアップロード(AWS CLIを利用)
- 文字起こしジョブの作成(Python SDK)
- 文字起こしジョブのステータス確認(Python SDK)
- 文字起こし結果の取得
- 文字起こしテキストを確認
- データの削除
1. 音源をアップロードする S3 バケットの作成(AWS CLIを利用)
S3 バケットを作成し、Amazon Transcribe がこのバケットを参照できるようにポリシー設定します。
リージョンの設定
リージョンを N. Virginia に固定します
$ export AWS_DEFAULT_REGION=us-east-1
この環境変数は AWS CLI/Python SDK に限らず AWS SDK 全般で有効です。
S3 バケットの作成
$ BUCKET=DUMMY $ aws s3 mb s3://$BUCKET make_bucket: DUMMY
S3 バケットポリシーの変更
Amazon Transcribe がこの S3 バケットのオブジェクトを参照できるようにバケットポリシーを設定します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "transcribe.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DUMMY/*" } ] }
"Resource": "arn:aws:s3:::DUMMY/*"
の箇所は、実際のバケット名に変更して下さい。
このポリシーをバケットに設定します。
$ aws s3api put-bucket-policy --bucket $BUCKET --policy file://policy.json $ aws s3api get-bucket-policy --bucket $BUCKET { "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"transcribe.amazonaws.com\"},\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::DUMMY/*\"}]}" }
詳細は次のドキュメントを参照ください。
2. 音源のアップロード(AWS CLIを利用)
オーディオを S3 に PUT します。
$ aws s3 cp YOUR-AUDIO.mp4 s3://$BUCKET/input/ upload: ./YOUR-AUDIO.mp4 to s3://DUMMY/input/YOUR-AUDIO.mp4
2018/04/12 時点で対応しているフォーマットは以下です
- WAV
- MP3
- MP4
- FLAC
3. 文字起こしジョブの作成(Python SDK)
準備が整ったところで、ようやく Amazon Transcribe API を使って、文字起こしジョブを開始する API start-transcription-job
を投げます。
サービスオブジェクトの初期化
まずは Amazon Transcribe サービスを操作するためのオブジェクトを作成します。
In [1]: import boto3 In [2]: client = boto3.client('transcribe')
文字起こしジョブの開始
In [3]: file_uri = 'https://s3.amazonaws.com/YOUR-BUCKET/input/YOUR-AUDRIO.mp4' In [4]: job_name = 'YOUR-JOB-NAME' In [9]: client.start_transcription_job( ...: TranscriptionJobName=job_name, ...: Media={ ...: 'MediaFileUri': file_uri ...: }, ...: MediaFormat='mp4', ...: MediaSampleRateHertz=44100, ...: LanguageCode='en-US', ...: Settings={ ...: 'VocabularyName' : 'aws', ...: 'ShowSpeakerLabels' : True, ...: 'MaxSpeakerLabels' : 3 ...: } ...: ) ...: Out[9]: {'TranscriptionJob': {'TranscriptionJobName': 'YOUR-JOB-NAME', 'TranscriptionJobStatus': 'IN_PROGRESS', 'LanguageCode': 'en-US', 'MediaSampleRateHertz': 44100, 'MediaFormat': 'mp4', 'Media': {'MediaFileUri': 'https://s3.amazonaws.com/YOUR-BUCKET/input/YOUR-AUDRIO.mp4'}, 'CreationTime': datetime.datetime(2018, 4, 11, 21, 58, 2, 976000, tzinfo=tzlocal()), 'Settings': {'VocabularyName': 'aws', 'ShowSpeakerLabels': True, 'MaxSpeakerLabels': 3}}, 'ResponseMetadata': {...}}
- 引数
TranscriptionJobName
には AWS アカウント内でユニークなジョブ名を指定します。重複していると「An error occurred (BadRequestException) when calling the StartTranscriptionJob operation: The requested job name already exists. Use a different job name.」と言うエラーが発生しました。 - 引数
LanguageCode
は 英語(en-US)とスペイン語(es-US)の二択です - 引数
MediaFormat
は mp3 | mp4 | wav | flac の4択です - 引数
MediaFormat
は mp3 | mp4 | wav | flac の4択です - 引数
Settings
はオプションです。カスタム語彙を利用する場合、VocabularyName
で語彙を指定します。話者を識別する場合はShowSpeakerLabels
,MaxSpeakerLabels
(話者の数) を指定して下さい。
カスタム語彙の詳細は次の記事を参照して下さい
話者の識別の詳細は次の記事を参照して下さい。
4. 文字起こしジョブのステータス確認(Python SDK)
ジョブのステータスを API get-transcription-job
で確認します。
In [10]: status = client.get_transcription_job(TranscriptionJobName=job_name) In [12]: status Out[12]: {'TranscriptionJob': {'TranscriptionJobName': 'YOUR-JOB-NAME', 'TranscriptionJobStatus': 'COMPLETED', 'LanguageCode': 'en-US', 'MediaSampleRateHertz': 44100, 'MediaFormat': 'mp4', 'Media': {'MediaFileUri': 'https://s3.amazonaws.com/YOUR-BUCKET/input/YOUR-AUDRIO.mp4'}, 'Transcript': {'TranscriptFileUri': 'https://s3.amazonaws.com/aws-transcribe-us-east-1-prod/123456789012/DUMMY'}, 'CreationTime': datetime.datetime(2018, 4, 11, 21, 58, 2, 976000, tzinfo=tzlocal()), 'CompletionTime': datetime.datetime(2018, 4, 11, 21, 59, 6, 551000, tzinfo=tzlocal()), 'Settings': {'VocabularyName': 'aws', 'ShowSpeakerLabels': True, 'MaxSpeakerLabels': 3}}, 'ResponseMetadata': {...}}
ステータスはジョブ開始直後の IN_PROGRESS
から COMPLETED
または FAILED
に遷移します。
ジョブ開始直後
{ "TranscriptionJob": { "TranscriptionJobName": "123", "LanguageCode": "en-US", "TranscriptionJobStatus": "IN_PROGRESS", "Media": { "MediaFileUri": "https://s3.amazonaws.com/DUMMY/input/test.mp4" }, "CreationTime": 1520808476.722, "MediaFormat": "mp4", "Transcript": {} } }
ジョブ正常完了後
{ "TranscriptionJob": { "TranscriptionJobName": "123", "LanguageCode": "en-US", "MediaSampleRateHertz": 44100, "TranscriptionJobStatus": "COMPLETED", "Media": { "MediaFileUri": "https://s3.amazonaws.com/DUMMY/input/test.mp4" }, "CreationTime": 1520808476.722, "CompletionTime": 1520808816.455, "MediaFormat": "mp4", "Transcript": { "TranscriptFileUri": "https://s3.amazonaws.com/aws-transcribe-us-east-1-prod/123456789012/123/asrOutput.json?DUMMY" } } }
文字起こしされたテキストは Amazon Transcribe が管理する S3 バケット s3://aws-transcribe-us-east-1-prod/AWS-ACCOUNT-ID/JOB-ID/asrOutput.json に保存されます。 このオブジェクトにアクセスするための presigned URL をジョブ結果の TranscriptionJob.Transcript.TranscriptFileUri に出力されています。
"asrOutput.json" の "asr" は "automatic speech recognition" の略と思います。
5. 文字起こし結果の取得
この asrOutput.json を HTTPS で取得します。
$ curl -o 123.asrOutput.json \ "https://s3.amazonaws.com/aws-transcribe-us-east-1-prod/123456789012/123/asrOutput.json?X-Amz-Security-Token=DUMMY"
この presigned URL は 15 分(899秒)だけ有効です。transcript 自体は90日取得可能です。
なお presigned URL が expire している場合は、以下のようなメッセージが出力されます。
<Error> <Code>AccessDenied</Code> <Message>Request has expired</Message> <X-Amz-Expires>899</X-Amz-Expires> <Expires>2018-03-11T07:11:38Z</Expires> <ServerTime>2018-03-11T23:01:30Z</ServerTime> <RequestId>DUMMY</RequestId> <HostId>DUMMY</HostId> </Error>
6. 文字起こしテキストを確認
アウトプットは JSON です
アウトプットの全体の抜粋です
{ "jobName": "YOUR-JOB-NAME", "accountId": "123456789012", "results": { "transcripts": [ { "transcript": "..." } ], "speaker_labels": { "speakers": 2, "segments": [ ... ] }, "items": [ ... ] }, "status": "COMPLETED" }
この JSON ファイルは以下の情報を含んでいます。
- speech-to-text 結果(
results.transcripts.transcript
) - text-to-speech 用に、各単語がいつ出現したか(
results.transcripts.items
) - 話者情報(
results.speaker_labels
)
speaker_labels
は話者の識別を有効にしてジョブを実行した場合のみ含まれます。
例として、asr の JSON ファイルから transcription 全体を出力してみます。
$ cat 123.asrOutput.json | jq ".results.transcripts[].transcript" How about language ? You know, i talked earlier about the fact that last year we launched both polly and relax...
7. データの削除
transcribe 結果は自分の管轄外の S3 バケットに保存されます。 このデータを削除する API は現時点では存在しません。 AWS サポート経由で削除を依頼してください。
FAQ から引用します。
Q. Can I delete voice inputs stored by Amazon Transcribe?
Yes. You can request deletion of voice inputs associated with your account by contacting AWS Support. Deleting voice inputs may degrade your Amazon Transcribe experience.
https://aws.amazon.com/transcribe/faqs/
まとめ
Amazon Transcribe を AWS SDK for Python (Boto) から利用しました。
このサービスを利用する上で一番気をつけるべきは transcription はユーザーが管理する S3 バケットではなく AWS が管理する S3 バケットに出力されることです。
文字起こしされたテキストは presigned URL を HTTPS GET する以外に取得する方法がありません。
- transcription ファイルへのアクセスを制御する
- transcription ファイルの削除方針を制御する
といった事はできないため、お気をつけ下さい。
また、企業・地域によってはオーディオデータや処理されたデータの管理が気になると思われます。
こちらについては FAQ の Data Privacy を一読ください。
参考
- https://docs.aws.amazon.com/transcribe/latest/dg/getting-started.html
- https://aws.amazon.com/transcribe/faqs/